// 闭包的概念

/**
 * 闭包是基于词法作用域书写代码时所产生的自然结果，你甚至不需要为了利用它们而有意
 * 识地创建闭包。闭包的创建和使用在你的代码中随处可见。你缺少的是根据你自己的意愿
 * 来识别、拥抱和影响闭包的思维环境。
 */

// function foo() {
//     var a = 2
//     function bar() {
//         console.log(a)
//     }
//     bar()
// }
// foo() //2

/**
 * 这段代码看起来和嵌套作用域中的示例代码很相似。基于词法作用域的查找规则，函数
 * bar() 可以访问外部作用域中的变量 a（这个例子中的是一个 RHS 引用查询）。
 * 这是闭包吗？
 * 技术上来讲，也许是。但根据前面的定义，确切地说并不是。我认为最准确地用来解释
 * bar() 对 a 的引用的方法是词法作用域的查找规则，而这些规则只是闭包的一部分。（但却
 * 是非常重要的一部分！
 */

// function foo(params) {
//     var a = params
//     function bar() {
//         console.log(a)
//     }
//     return bar
// }
// let baz = foo(2)
// baz() //2

/**
 * 函数 bar() 的词法作用域能够访问 foo() 的内部作用域。然后我们将 bar() 函数本身当作
 * 一个值类型进行传递。在这个例子中，我们将 bar 所引用的函数对象本身当作返回值。
 * 在 foo() 执行后，其返回值（也就是内部的 bar() 函数）赋值给变量 baz 并调用 baz()，实
 * 际上只是通过不同的标识符引用调用了内部的函数 bar()。
 * bar() 显然可以被正常执行。但是在这个例子中，它在自己定义的词法作用域以外的地方
 * 执行。
 * 在 foo() 执行后，通常会期待 foo() 的整个内部作用域都被销毁，因为我们知道引擎有垃
 * 圾回收器用来释放不再使用的内存空间。由于看上去 foo() 的内容不会再被使用，所以很
 * 自然地会考虑对其进行回收。
 * 而闭包的“神奇”之处正是可以阻止这件事情的发生。事实上内部作用域依然存在，因此
 * 没有被回收。谁在使用这个内部作用域？原来是 bar() 本身在使用。
 * 拜 bar() 所声明的位置所赐，它拥有涵盖 foo() 内部作用域的闭包，使得该作用域能够一
 * 直存活，以供 bar() 在之后任何时间进行引用。
 * bar() 依然持有对该作用域的引用，而这个引用就叫作闭包。
 */

/**
 * 闭包与两个特性有关，一是嵌套作用域，另一个是函数当值传递（first-class function），
 * 前者能让作用域内部访问外部变量，后者是函数式编程的前提。
 * 两者使得 JavaScript 非常灵活，除非你打算把 ES6 当作静态语言来编写，否则你总会用到闭包的
 */
function wait(message) {
    setTimeout(function timer() {
        console.log(message)
    },1000)
}
wait("这是一段话")